package com.cn.onetrip.untility;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Camera.Size;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;

public class SyncBitmapLoader {

	private Object lock = new Object();

	private boolean mAllowLoad = true;

	private boolean firstLoad = true;

	private int mStartLoadLimit = 0;

	private int mStopLoadLimit = 0;

	final Handler handler = new Handler();

	private Context mContext;

	RunInOtherThread runInOutherThread;

	private int bmpWidth = 0;
	private int bmpHeight = 0;

	public SyncBitmapLoader(Context context) {
		super();
		this.mContext = context;
		runInOutherThread = new RunInOtherThread();
		runInOutherThread.start();
	}

	public interface OnImageLoadListener {
		public void onBitmapLoad(Bitmap bitmap);

		public void onGetBitmapWH(int width, int height);

		public void onError();
	}

	public void setLoadLimit(int startLoadLimit, int stopLoadLimit) {
		if (startLoadLimit > stopLoadLimit) {
			return;
		}
		mStartLoadLimit = startLoadLimit;
		mStopLoadLimit = stopLoadLimit;
	}

	public void restore() {
		mAllowLoad = true;
		firstLoad = true;
	}

	public void lock() {
		mAllowLoad = false;
		firstLoad = false;
	}

	public void unlock() {
		mAllowLoad = true;
		synchronized (lock) {
			lock.notifyAll();
		}
	}

	public void loadBitmap(String imageUrl, OnImageLoadListener listener) {
		final OnImageLoadListener mListener = listener;
		final String mImageUrl = imageUrl;

		Handler handerTest = runInOutherThread.getHandler();
		if (handerTest == null) {
			handerTest = runInOutherThread.getHandler();
		}
		if (handerTest != null) {
			handerTest.post(new Runnable() {
				@Override
				public void run() {
					if (!mAllowLoad) {
						synchronized (lock) {
							try {
								DebugUtil.debug("wait start.....");
								lock.wait();
								DebugUtil.debug("wait end.....");
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}
					if (mAllowLoad) {
						loadImage1(mImageUrl, mListener);
					}
				}
			});
		}
	}

	private void loadImage1(final String mImageUrl,
			final OnImageLoadListener mListener) {

		try {
			getBmpWHFromUrl(mImageUrl);
		} catch (IOException e1) {
			mListener.onGetBitmapWH(0, 0);
		}

		try {
			final Bitmap bmp = loadImageFromUrl(mImageUrl);
			handler.post(new Runnable() {
				@Override
				public void run() {
					if (mAllowLoad) {
						mListener.onBitmapLoad(bmp);
						mListener.onGetBitmapWH(bmpWidth, bmpHeight);
					}
				}
			});

		} catch (IOException e) {
			handler.post(new Runnable() {
				@Override
				public void run() {
					mListener.onError();
				}
			});
			e.printStackTrace();
		}
	}

	private void getBmpWHFromUrl(String url) throws IOException {
		
		File file = new File(url);
		if (file.exists()) {
			FileInputStream fis = new FileInputStream(file);
			getBmpWH(fis);
			fis.close();
			
		} else {
			File f = new File(HTTPUrl.ImageCacheFloder + "/" + MD5.getMD5(url));
			if (f.exists()) {
				FileInputStream fis = new FileInputStream(f);
				getBmpWH(fis);
				fis.close();
				return;
			}

			URL m = new URL(url);
			InputStream is = (InputStream) m.getContent();
			getBmpWH(is);
			is.close();
		}
	}

	private Bitmap loadImageFromUrl(String url) throws IOException {
		if (url == null || url.length() == 0)
			return null;

//		DebugUtil.debug(url);
		File file = new File(url);
		Bitmap bitmap = null;
		Drawable drawable = null;
		if (file.exists()) {
			bitmap = decodeFileStream(file, 1);

			return bitmap;
		} else {
			File f = new File(HTTPUrl.ImageCacheFloder + "/" + MD5.getMD5(url));
			if (f.exists()) {
				bitmap = decodeFileStream(f, 1);
				if (bitmap != null) {
					return bitmap;
				}
			}

			URL m = new URL(url);
			try {
				InputStream is = (InputStream) m.getContent();
				DataInputStream in = new DataInputStream(is);
				FileOutputStream out = new FileOutputStream(f);
				byte[] buffer = new byte[1024];
				int byteread = 0;
				while ((byteread = in.read(buffer)) != -1) {
					out.write(buffer, 0, byteread);
				}

				out.close();
				in.close();
				is.close();
				return loadImageFromUrl(url);

			} catch (Exception e) {
				bitmap = decodeStream(m, 1);

				return bitmap;
			}
		}
	}

	private void getBmpWH(InputStream is) {
		BitmapFactory.Options opts = new BitmapFactory.Options();
		opts.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(is, null, opts);
		bmpWidth = opts.outWidth;
		bmpHeight = opts.outHeight;
	}

	private Bitmap decodeFileStream(File file, int sampleSize)
			throws IOException {
		Bitmap bitmap = null;
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = sampleSize;
		options.inJustDecodeBounds = false;
		FileInputStream fis = null;

		try {
			fis = new FileInputStream(file);
			bitmap = BitmapFactory.decodeStream(fis, null, options);
		} catch (OutOfMemoryError e) {
			if (bitmap != null && !bitmap.isRecycled()) {
				bitmap.recycle();
				bitmap = null;
			}

			sampleSize++;
			bitmap = decodeFileStream(file, sampleSize);
		} catch (Exception e) {
			if (bitmap != null && !bitmap.isRecycled()) {
				bitmap.recycle();
				bitmap = null;
			}

			sampleSize++;
			bitmap = decodeFileStream(file, sampleSize);
			e.printStackTrace();
			Log.i("Exception", e.getMessage());
		} finally {
			if (fis != null) {
				fis.close();
				System.gc();
			}
		}

		return bitmap;
	}

	private Bitmap decodeStream(URL url, int sampleSize) throws IOException {
		Bitmap bitmap = null;
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = sampleSize;
		options.inJustDecodeBounds = false;
		InputStream is = null;

		try {
			is = (InputStream) url.getContent();
			bitmap = BitmapFactory.decodeStream(is, null, options);
		} catch (OutOfMemoryError e) {
			if (bitmap != null && !bitmap.isRecycled()) {
				bitmap.recycle();
				bitmap = null;
			}

			sampleSize++;
			bitmap = decodeStream(url, sampleSize);
		} finally {
			if (is != null) {
				is.close();
				System.gc();
			}
		}
		return bitmap;
	}

	public void threadQuit() {
		// TODO Auto-generated method stub
		if (runInOutherThread != null) {
			runInOutherThread.quit();
		}

	}
}
